package com.cash.app.net

import com.google.gson.Gson
import com.cash.app.net.NetConstant.E_BODY_NULL
import com.cash.app.net.NetConstant.E_HTTP
import com.cash.app.net.NetConstant.E_HTTP_UNKNOW
import com.cash.app.net.NetConstant.REC_BODY_EMPTY
import com.cash.app.net.NetConstant.REC_HTTP_EXCEPTION
import com.cash.app.utils.TLog
import retrofit2.Response

object NetRequestExecutor {

    private val TAG = "NetRequestExecutor"
    private val gson = Gson()

    // common BaseResponse<T>
    suspend fun <T> baseNetRequest(netRequest: suspend () -> Response<BaseResponse<T>>): NetResult<T> {
        return try {
            val response = netRequest()
            if (response.isSuccessful) {
                val body: BaseResponse<T>? = response.body()
                when {
                    body === null -> NetResult.Error(REC_BODY_EMPTY, E_BODY_NULL)
                    body.isSuccess() -> NetResult.Success(body.result)
                    else -> NetResult.Error(body.returnCode, body.msg)
                }
            } else {
                // Try to parse error body
                try {
                    val errorBody = response.errorBody()?.string()
                    if (errorBody != null) {
                        val errorRsp = gson.fromJson(errorBody, BaseResponse::class.java)
                        TLog.e("parse error body msg=${errorRsp.msg}", TAG)
                        return NetResult.Error(errorRsp.returnCode, errorRsp.msg)
                    }
                } catch (e: Exception) {
                    TLog.e("parse error body exception", TAG, e)
                }
                return NetResult.Error(response.code(), "$E_HTTP ${response.message()}")
            }
        } catch (e: Exception) {
            NetResult.Exception(REC_HTTP_EXCEPTION, "$E_HTTP_UNKNOW ${e.message}")
        }
    }

    // custom Response
    suspend fun <T> otherNetRequest(netRequest: suspend () -> Response<T>): NetResult<T> {
        return try {
            val response = netRequest()
            if (response.isSuccessful) {
                val body: T? = response.body()
                when {
                    body === null -> NetResult.Error(REC_BODY_EMPTY, E_BODY_NULL)
                    else -> NetResult.Success(body)
                }
            } else {
                NetResult.Error(response.code(), "$E_HTTP ${response.message()}")
            }
        } catch (e: Exception) {
            NetResult.Exception(REC_HTTP_EXCEPTION, "$E_HTTP_UNKNOW ${e.message}")
        }
    }
}